/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MainPackage;

import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.util.Iterator;
import java.util.Set;

import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.DefaultEdge;

/**
 * 
 * @author Santosh
 */
public class FileM {

	private String HOMEPATH;

	public FileM() {
		super();
	}

	public FileM(String HOMEPATH) {
		this();
		this.HOMEPATH = HOMEPATH;
	}

	// This method prints the elements of a given HashSet object.
	public static void printHashSet(HashSet<String> hashSet) {
		System.out.print("HashSet: ");

		// Use an Iterator to print each element of the TreeSet.
		Iterator<String> iterator = hashSet.iterator();
		while (iterator.hasNext())
			System.out.print(iterator.next() + ", ");
		System.out.println();
	}

	public String[] countTags(String iFileName) throws FileNotFoundException,
			IOException {

		System.out.println("CountTags: Method Entry: " + iFileName);
		String[] featureCount = new String[Settings.FEATURECOUNT];
		int recordCount = 0;

		File outputFile = new File(Settings.HOMEPATH + "\\"
				+ "nodeStatsNew.csv");
		FileWriter fileStream = new FileWriter(outputFile);
		BufferedWriter out = new BufferedWriter(fileStream);

		try {

			File inputFile = new File(Settings.HOMEPATH + "\\" + iFileName);
			Scanner fileScanner = new Scanner(inputFile);

			while (fileScanner.hasNext()) {
				String currRecord = fileScanner.next();
				String[] currRecordSplit = currRecord.split(",");
				// System.out.println(currRecordSplit.length);
				String[] currRecordFeatures = currRecordSplit[2].split("");
				int tempCount = 0;
				int groupCount = 0;
				int tagCount = 0;
				int labelCount = 0;
				int totalCount = 0;
				for (int i = 0; i < 9101; i++) {
					totalCount++;
					if (currRecordFeatures[i].equals("1")) {
						tempCount++;
						groupCount++;
					}
				}

				for (int i = 9101; i < 26905; i++) {
					totalCount++;
					if (currRecordFeatures[i].equals("1")) {
						tempCount++;
						tagCount++;
					}
				}

				for (int i = 26905; i < currRecordFeatures.length; i++) {
					totalCount++;
					if (currRecordFeatures[i].equals("1")) {
						tempCount++;
						labelCount++;
					}
				}

				featureCount[recordCount] = currRecordSplit[0] + ","
						+ tempCount + "," + groupCount + "," + tagCount + ","
						+ labelCount + "," + totalCount;

				out.write(currRecordSplit[0] + "," + tempCount + ","
						+ groupCount + "," + tagCount + "," + labelCount + ","
						+ (totalCount - 1));
				out.newLine();

				// System.out.println(featureCount[recordCount]);

				recordCount++;
			}

		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
			e.printStackTrace();
		}

		out.close();
		return featureCount;

	}

	public boolean writeStringToFile(String[] outputString, String OUTPUTFILE)
			throws IOException {
		System.out.println("writeStringToFile: Method Entry: " + OUTPUTFILE);
		try {
			File outputFile = new File(HOMEPATH + "\\" + OUTPUTFILE);
			FileWriter fileStream = new FileWriter(outputFile);
			BufferedWriter out = new BufferedWriter(fileStream);

			System.out.println("No. of records: " + outputString.length);

			for (String writeString : outputString) {
				out.write(writeString);
				out.newLine();
			}

			out.close();
			return true;
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
			e.printStackTrace();
			return false;
		}

	}

	public void filterEdgesByNodes(String nodeFile, String edgeFile,
			String outputFile) throws IOException {
		// TODO Auto-generated method stub
		System.out.println("filterEdgesByNodes: Method Entry: Node File: "
				+ nodeFile + ", Edge File: " + edgeFile + ", Output File: "
				+ outputFile);

		// Read all nodes and keep them in a hash

		File inputNodeFile = new File(HOMEPATH + "\\" + nodeFile);
		Scanner nodeScanner = new Scanner(inputNodeFile);

		HashSet<String> hs = new HashSet<String>();

		int nodeCount = 0;

		while (nodeScanner.hasNext()) {
			String currLine = nodeScanner.next();
			String[] currColumns = currLine.split(",");
			String nodeId = currColumns[0];

			if (!hs.contains(nodeId)) {
				hs.add(nodeId);
				nodeCount++;
			}
		}

		System.out.println("Completed reading nodes. Total no. of nodes: "
				+ nodeCount);

		// Read all edges and keep an edge if both nodes of that edge are
		// in the nodes hash set.

		File inputEdgeFile = new File(HOMEPATH + "\\" + edgeFile);
		Scanner edgeScanner = new Scanner(inputEdgeFile);

		File oFile = new File(HOMEPATH + "\\" + outputFile);
		FileWriter fileStream = new FileWriter(oFile);
		BufferedWriter out = new BufferedWriter(fileStream);

		int edgeCount = 0;

		HashSet<String> edgeHs = new HashSet<String>();
		int nodesInEdges = 0;

		while (edgeScanner.hasNext()) {
			String currLine = edgeScanner.next();
			// System.out.println(currLine);
			String[] currEdges = currLine.split(",");
			// System.out.println(currEdges.length);
			if (hs.contains(currEdges[0]) && hs.contains(currEdges[1])) {

				out.write(currEdges[0] + "	" + currEdges[1]);
				out.newLine();
				edgeCount++;

				if (!edgeHs.contains(currEdges[0])) {
					edgeHs.add(currEdges[0]);
					nodesInEdges++;

				}

				if (!edgeHs.contains(currEdges[1])) {
					edgeHs.add(currEdges[1]);
					nodesInEdges++;

				}

			}

		}

		out.close();

		System.out
				.println("Completed writing edges. Total edges: " + edgeCount);
		System.out.println("Nodes in edges: " + nodesInEdges);

	}

	public String[] getNodeMeta(String nodeMetaData)
			throws FileNotFoundException {
		// TODO Auto-generated method stub

		System.out.println("getNodeMeta : Method Entry");

		File inputFile = new File(Settings.HOMEPATH + "\\" + nodeMetaData);
		Scanner scanner = new Scanner(inputFile);

		String[] metaData = new String[Settings.FEATURECOUNT];
		int i = 0;
		System.out.println("MetaData Length: " + metaData.length);
		while (scanner.hasNext()) {
			String currLine = scanner.next();
			String[] tagString = currLine.split(",");
			metaData[i] = tagString[1];
			i++;
		}

		System.out.println("getNodeMeta : Method Exit");

		return metaData;
	}

	public Map<String, Map<String, Integer>> getFeatureVector(
			UndirectedGraph<String, DefaultEdge> stringGraph,
			String nodeDataFile, String[] nodeMeta)
			throws FileNotFoundException {

		System.out.println("getFeatureVector : Method Entry");

		File inputFile = new File(Settings.HOMEPATH + "\\" + nodeDataFile);
		Scanner scanner = new Scanner(inputFile);

		String[] vectors = new String[Settings.NODESCOUNT];
		Map<String, Map<String, Integer>> vectorMap = new HashMap<String, Map<String, Integer>>();

		Set<String> vertices = stringGraph.vertexSet();

		int i = 0;

		while (scanner.hasNext()) {
			String currVector = scanner.next();
			String[] currVectorSplit = currVector.split(",");
			if (vertices.contains(currVectorSplit[0])) {
				String[] currTagVectorSplit = currVectorSplit[2].split("");

				/*
				 * System.out.println("F: "+currTagVectorSplit[0]);
				 * System.out.println("S: "+currTagVectorSplit[1]);
				 * System.out.println
				 * ("L: "+currTagVectorSplit[currTagVectorSplit.length-1]);
				 */

				for (int k = 0; k < 27120; k++) {

					int metaIndex = k - 1;
					// System.out.println(eachTag + ", "+metaIndex+ ", "+ i);
					if (currTagVectorSplit[k].equals("1")) {
						vectors[i] = "," + nodeMeta[metaIndex];
						Map<String, Integer> tagMap = vectorMap
								.get(currVectorSplit[0]);
						if (tagMap == null) {
							tagMap = new HashMap<String, Integer>();
							tagMap.put(nodeMeta[metaIndex], 1);
						} else {
							if (tagMap.get(nodeMeta[metaIndex]) == null) {
								tagMap.put(nodeMeta[metaIndex], 1);
							} else {
								tagMap.put(nodeMeta[metaIndex],
										1 + tagMap.get(nodeMeta[metaIndex]));
							}
						}

						vectorMap.put(currVectorSplit[0], tagMap);
					}
				}
				i++;
			}
		}

		System.out.println("Feature Vectors in array with vectors in "
				+ "comma seperated string: " + vectors.length);

		System.out.println("Vectors in Map: " + vectorMap.size());

		System.out.println("getFeatureVector : Method Exit");
		return vectorMap;
	}

	/*
	 * public void printVectorMap(Map<String, Map<String, Integer>> vectorMap,
	 * String[] nodeMeta) { // TODO Auto-generated method stub
	 * System.out.println("printVectorMap : Method Entry");
	 * 
	 * for (String metaTag : nodeMeta) {
	 * 
	 * Iterator it = vectorMap.entrySet().iterator(); while (it.hasNext()) {
	 * Map.Entry pairs = (Map.Entry) it.next(); Map<String, Integer> tagMap =
	 * (Map<String, Integer>) pairs .getValue(); //
	 * System.out.println(pairs.getKey()); Iterator tagIterator =
	 * tagMap.entrySet().iterator(); String tempString = ""; while
	 * (tagIterator.hasNext()) { Map.Entry tagCountPair = (Map.Entry)
	 * tagIterator.next(); tempString += tagCountPair.getKey() + " ";
	 * tagIterator.remove(); }
	 * 
	 * System.out.println(tempString);
	 * 
	 * it.remove(); // }
	 * 
	 * }
	 * 
	 * 
	 * }
	 */

	public Map<String, Map<String, Short>> getTrainVectors(
			String nodeDataFile, String[] nodeMeta)
			throws FileNotFoundException {

		System.out.println("getTrainVector : Method Entry");
		
		File inputFile = new File(Settings.HOMEPATH + "\\" + nodeDataFile);
		Scanner scanner = new Scanner(inputFile);
		
		/*
		FileInputStream fstream = new FileInputStream(Settings.HOMEPATH + "\\" + nodeDataFile);
		DataInputStream in = new DataInputStream(fstream);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
		*/
		Map<String, Map<String, Short>> vectorMap = new HashMap<String, Map<String, Short>>();

		int readVectors = 0;
		while (scanner.hasNext()) {
			String currVector = scanner.next();
			String[] currTagVectorSplit = currVector.split(",");

			/*
			 * System.out.println("F: "+currTagVectorSplit[0]);
			 * System.out.println("S: "+currTagVectorSplit[1]);
			 * System.out.println
			 * ("L: "+currTagVectorSplit[currTagVectorSplit.length-1]);
			 */

			for (int k = 1; k < 27121; k++) {

				int metaIndex = k - 1;
				// System.out.println(eachTag + ", "+metaIndex+ ", "+ i);
				if (!currTagVectorSplit[k].equals("0")) {
					Map<String, Short> tagMap = vectorMap
							.get(currTagVectorSplit[0]);
					if (tagMap == null) {
						tagMap = new HashMap<String, Short>();
						tagMap.put(nodeMeta[metaIndex], (short) 1);
					} else {
						if (tagMap.get(nodeMeta[metaIndex]) == null) {
							tagMap.put(nodeMeta[metaIndex], (short) 1);
						} else {
							tagMap.put(nodeMeta[metaIndex],
									(short) (1 + tagMap.get(nodeMeta[metaIndex])));
						}
					}

					vectorMap.put(currTagVectorSplit[0], tagMap);
				}
			}
			
			if(readVectors % 100 == 0){
				
				System.out.println("Read "+readVectors+ " so far.. still reading.. ");
				int mb = 1024*1024;
		         
		        //Getting the runtime reference from system
		        Runtime runtime = Runtime.getRuntime();
		         
		        System.out.println("##### Heap utilization statistics [MB] #####");
		         
		        //Print used memory
		        System.out.println("Used Memory:"
		            + (runtime.totalMemory() - runtime.freeMemory()) / mb);
		 
		        //Print free memory
		        System.out.println("Free Memory:"
		            + runtime.freeMemory() / mb);
		         
		        //Print total available memory
		        System.out.println("Total Memory:" + runtime.totalMemory() / mb);
		 
		        //Print Maximum available memory
		        System.out.println("Max Memory:" + runtime.maxMemory() / mb);
				
			}
			
			readVectors++;
		}

		System.out.println("Vectors in Map: " + vectorMap.size());

		System.out.println("getTrainVector : Method Exit");
		return vectorMap;
	}

}
